#include "ulib.h"
#include "string.h"
#include "task.h"



static TBool GroupStateArray[ButtonsCount];
TMessage TempMessage;
TArray TransmiteArray;
TArray ReceiveArray;
char FROM_ME[]="SK1";
char TO_DEVICE_1[]="LK1";
uint8 CounterMessage=0;
char PWR_ON[]="ON";
char PWR_OFF[]="OFF";
char MSG_OK[]="OK";

int ReadArray(TArray *Array, void *Element){
	uint32 i;
	if ((Array->ElementCount>0)&&(Array->ElementCount<=Array->MaxCount)){
		for(i=0;i<Array->ElementSize;i++){
			*((uint8 *)Element+i)=*((uint8 *)(Array->Buffer)+
				(Array->ElementSize)*(Array->MaxCount-Array->ElementCount)+i);
		}
		Array->ElementCount--;
	} else return -1;
	return 0;
}

int WriteArray(TArray *Array, void *Element){
	uint32 i;
	if ((Array->MaxCount>0)&&(Array->ElementCount<Array->MaxCount)){
	Array->ElementCount++;
	for(i=0;i<Array->ElementSize;i++){
			*((uint8 *)(Array->Buffer)+(Array->ElementSize)*
					(Array->MaxCount-Array->ElementCount)+i)=*((uint8 *)Element+i);
		}
	} else return -1;
	return 0;
}

void EraseObj(void *Obj,uint32 Size){
	int i;
	for(i=0;i<Size;i++){
		*((uint32 *)Obj+i)=0;
	}
}

int AddMessage(TArray *Array, TMessage *Message){
	TMessage *M;
	uint8 i,k;
	for(i=0;i<Array->MaxCount;i++){
		M=(TMessage *)(Array->Buffer+i*Array->ElementSize);
		if (M->TTL==0){
			for(k=0;k<Array->ElementSize;k++){
				*((uint8 *)M+k)=*((uint8 *)Message+k);
			}
			return 0;
		}
	}
	return -1;
}

void SetTTL(TArray *Array, uint8 Number, uint8 TTL){
	TMessage *M;
	uint8 i;
	for(i=0;i<Array->MaxCount;i++){
		M=(TMessage *)(Array->Buffer+i*Array->ElementSize);
		if (M->Number==Number){
			M->TTL=TTL;
		}
	}
}

int PrepMessage(TArray *Array, void *Buffer){
	uint8 i,k;
	TMessage *M;
	for(i=0;i<Array->MaxCount;i++){
		M=(TMessage *)(Array->Buffer+i*Array->ElementSize);
		if (M->TTL>0){
			for(k=0;k<Array->ElementSize;k++){
				*((uint8 *)Buffer+k)=*((uint8 *)M+k);
			}
			M->TTL--;
			return 0;
		}
	}
	return -1;
}

void GetMessage(TArray *Array, uint8 *Buffer, uint32 BufferSize, uint8 *TempBuffer){
	uint32 i,k;
	for(i=0;i<BufferSize;i++){
		if(*(Buffer+i)==STARTByte){
			if((BufferSize<(i+Array->ElementSize))&&
					(*(Buffer+i+Array->ElementSize-BufferSize-1)==ENDByte)){
				for(k=i;k<BufferSize;k++){
					*(TempBuffer+k-i)=*(Buffer+k);
				}
				for(k=0;k<(i+Array->ElementSize-BufferSize);k++){
					*(TempBuffer+k)=*(Buffer+k);
				}
				if (WriteArray(Array,TempBuffer)==0){
					EraseObj(Buffer+i,BufferSize-i);
					EraseObj(Buffer,i+Array->ElementSize-BufferSize);
				}
			}
			if((BufferSize>=(i+Array->ElementSize))&&(*(Buffer+i+Array->ElementSize)==ENDByte)){
				if (WriteArray(Array,Buffer+i)==0)
					EraseObj(Buffer+i,Array->ElementSize);
			}
		}
	}
}


void CommandLoop(TArray *RecArray, TArray *TransArray, void *TempBuffer){
	TMessage *M;
	TBool Answer=false;
	M=(TMessage *)TempBuffer;
	if (ReadArray(RecArray,TempBuffer)==0){
		if (strcmp(M->To,FROM_ME)==0){
			if (strcmp(M->Command,MSG_OK)==0){
				SetTTL(TransArray,M->Number,0);
			}
		}
	}
	if(Answer==true){
		taskENTER_CRITICAL();
		EraseObj(&TempMessage,sizeof(TMessage));
		TempMessage.StartByte=STARTByte;
		TempMessage.EndByte=ENDByte;
		strcpy(TempMessage.Command,MSG_OK);
		strcpy(TempMessage.From,FROM_ME);
		strcpy(TempMessage.To,M->From);
		TempMessage.Number=CounterMessage;
		TempMessage.TTL=3;
		AddMessage(&TransmiteArray,&TempMessage);
		taskEXIT_CRITICAL();
	}
}

void EnableRCC(TPin *Pin){
	uint32 *RCC_APB2_Enable;
	RCC_APB2_Enable=(uint32 *)RCC_APB2_Base;
	switch(Pin->Port){
	case 'A': *RCC_APB2_Enable |= GPIOA_Enable; break;
	case 'B': *RCC_APB2_Enable |= GPIOB_Enable; break;
	case 'C': *RCC_APB2_Enable |= GPIOC_Enable; break;
	case 'D': *RCC_APB2_Enable |= GPIOD_Enable; break;
	};
}

void EnableUSARTRCC(TUART *UART){
	uint32 *APB2;
	APB2=(uint32 *)RCC_APB2_Base;
	uint32 *APB1;
	APB1=(uint32 *)RCC_APB1_Base;
	switch(UART->Number){
	case 1: *APB2 |= USART1_Enable; break;
	case 2: *APB1 |= USART2_Enable; break;
	case 3: *APB1 |= USART3_Enable; break;
	};
}

void EnableDMARCC(void){
	uint32 *AHB=(uint32 *)RCC_AHB_Base;
	*AHB |= 0x03;
}

DMA_Channel_TypeDef *GetDMAChannel(uint8 Channel){
	//return (DMA_Channel_TypeDef *)(DMA1_Base+0x08+20*(DMA->Channel-1));
	DMA_Channel_TypeDef *DMAc=DMA1_Channel1;
	switch(Channel){
	case 1:DMAc=DMA1_Channel1; break;
	case 2:DMAc=DMA1_Channel2; break;
	case 3:DMAc=DMA1_Channel3; break;
	case 4:DMAc=DMA1_Channel4; break;
	case 5:DMAc=DMA1_Channel5; break;
	case 6:DMAc=DMA1_Channel6; break;
	case 7:DMAc=DMA1_Channel7; break;
	}
	return DMAc;
}



void ReadUARTtoDMA(TUART *UART, TDMAChannel *DMA, void *Buffer, uint32 BufferSize){
	StopDMAChannel(DMA->Channel);
	StopUART(UART);

	SetReadyPin(false); //hack !!!!!!!!!!

	UART->DMAReceiverEnable=true;
	UART->ReceiverEnable=true;
	UART->DMATransmitterEnable=false;
	UART->TransmitterEnable=false;
	UART->Interrupt.TransmissionComplete=false;
	SetUARTMode(UART);

	DMA->Channel=GetDMAChannelUART(UART,true);
	DMA->CircularMode=true;
	DMA->Direction=ToMemory;
	DMA->PeripheralAddress=(uint32)&GetUSART(UART)->DR;
	DMA->MemoryAddress=(uint32)Buffer;
	DMA->Size=BufferSize;
	DMA->Interrupt.TransmissionComplete=false;
	DMA->Enable=true;
	SetDMAMode(DMA);
}


void WriteDMAtoUART(TUART *UART, TDMAChannel *DMA, void *Buffer, uint32 BufferSize){
	StopDMAChannel(DMA->Channel);
	StopUART(UART);

	SetReadyPin(true); //hack !!!!!!!!!!
	UART->DMAReceiverEnable=false;
	UART->ReceiverEnable=false;
	UART->DMATransmitterEnable=true;
	UART->TransmitterEnable=true;
	UART->Interrupt.TransmissionComplete=true;
	SetUARTMode(UART);

	DMA->Channel=GetDMAChannelUART(UART,false);
	DMA->CircularMode=false;
	DMA->Direction=ToPeripheral;
	DMA->PeripheralAddress=(uint32)&GetUSART(UART)->DR;
	DMA->MemoryAddress=(uint32)Buffer;
	DMA->Size=BufferSize;
	DMA->Interrupt.TransmissionComplete=true;
	DMA->Enable=true;
	SetDMAMode(DMA);
}


void SetReadyPin(TBool Ready){
	TPinMode M;
	TPin Pin;
	Pin.Pin=2; Pin.Port='B';
	M.CNF=GenOutPP;
	M.Mode=OutMode10MHz;
	SetPinMode(&Pin,&M);
	if (Ready==true){
		SetBit(&Pin);
	} else {
		ReSetBit(&Pin);
	}
}

uint32 GetDMAChannelUART(TUART *UART, TBool ReadMode){
	if (ReadMode==true){
		switch(UART->Number){
			case 1:return 5;
			case 2:return 6;
			case 3:return 3;
			default: return 5;
		}
	}else{
		switch(UART->Number){
			case 1:return 4;
			case 2:return 7;
			case 3:return 2;
			default: return 4;
		}
	}
}



uint32 ConvertBaud(uint32 Baud){
	if (Baud>0) {
		return (uint32)((configCPU_CLOCK_HZ+Baud/2)/Baud);
	}
	return 0;
}

void StopUART(TUART *UART){
	USART_TypeDef *USART=GetUSART(UART);
	USART->CR1&=0x0000;
}

void StopDMAChannel(uint8 Channel){
	DMA_Channel_TypeDef *DMAx=GetDMAChannel(Channel);
	DMAx->CCR&=0x0000;
}

USART_TypeDef *GetUSART(TUART *UART){
	USART_TypeDef *USART;
	switch(UART->Number){
	case 1:USART=USART1; break;
	case 2:USART=USART2; break;
	case 3:USART=USART3; break;
	default: USART=USART1;
	}
	return USART;
}

void SetPinForUSART(TUART *UART){
	TPin Pin;
	TPinMode PinMode;
	switch(UART->Number){
		case 1:{
			Pin.Port='A'; Pin.Pin=9;//TX
			PinMode.CNF=AltOutPP; PinMode.Mode=OutMode50MHz;
			SetPinMode(&Pin,&PinMode);
			if ((UART->Mode==Async)||(UART->Mode==Hardware_RTS)||
					(UART->Mode==Hardware_CTS)||(UART->Mode==Hardware_RTS_CTS)){
				Pin.Port='A'; Pin.Pin=10;//RX
				PinMode.CNF=InFloat; PinMode.Mode=InMode;
				SetPinMode(&Pin,&PinMode);
			}
			if ((UART->Mode==Hardware_CTS)||(UART->Mode==Hardware_RTS_CTS)){
				Pin.Port='A'; Pin.Pin=11;//CTS
				PinMode.CNF=InFloat; PinMode.Mode=InMode;
				SetPinMode(&Pin,&PinMode);
			}
			if ((UART->Mode==Hardware_RTS)||(UART->Mode==Hardware_RTS_CTS)){
				Pin.Port='A'; Pin.Pin=12;//RTS
				PinMode.CNF=AltOutPP; PinMode.Mode=OutMode50MHz;
				SetPinMode(&Pin,&PinMode);
			}
			break;
		}
		case 2:{
			Pin.Port='A'; Pin.Pin=2;//TX
			PinMode.CNF=AltOutPP; PinMode.Mode=OutMode50MHz;
			SetPinMode(&Pin,&PinMode);
			if ((UART->Mode==Async)||(UART->Mode==Hardware_RTS)||
					(UART->Mode==Hardware_CTS)||(UART->Mode==Hardware_RTS_CTS)){
				Pin.Port='A'; Pin.Pin=3;//RX
				PinMode.CNF=InFloat; PinMode.Mode=InMode;
				SetPinMode(&Pin,&PinMode);
			}
			if ((UART->Mode==Hardware_CTS)||(UART->Mode==Hardware_RTS_CTS)){
				Pin.Port='A'; Pin.Pin=0;//CTS
				PinMode.CNF=InFloat; PinMode.Mode=InMode;
				SetPinMode(&Pin,&PinMode);
			}
			if ((UART->Mode==Hardware_RTS)||(UART->Mode==Hardware_RTS_CTS)){
				Pin.Port='A'; Pin.Pin=1;//RTS
				PinMode.CNF=AltOutPP; PinMode.Mode=OutMode50MHz;
				SetPinMode(&Pin,&PinMode);
			}
			break;
		}
		case 3:{
			Pin.Port='B'; Pin.Pin=10;
			PinMode.CNF=AltOutPP; PinMode.Mode=OutMode50MHz;
			SetPinMode(&Pin,&PinMode);
			if ((UART->Mode==Async)||(UART->Mode==Hardware_RTS)||
					(UART->Mode==Hardware_CTS)||(UART->Mode==Hardware_RTS_CTS)){
				Pin.Port='B'; Pin.Pin=11;//RX
				PinMode.CNF=InFloat; PinMode.Mode=InMode;
				SetPinMode(&Pin,&PinMode);
			}
			if ((UART->Mode==Hardware_CTS)||(UART->Mode==Hardware_RTS_CTS)){
				Pin.Port='B'; Pin.Pin=13;//CTS
				PinMode.CNF=InFloat; PinMode.Mode=InMode;
				SetPinMode(&Pin,&PinMode);
			}
			if ((UART->Mode==Hardware_RTS)||(UART->Mode==Hardware_RTS_CTS)){
				Pin.Port='B'; Pin.Pin=14;//RTS
				PinMode.CNF=AltOutPP; PinMode.Mode=OutMode50MHz;
				SetPinMode(&Pin,&PinMode);
			}
			break;
		}
	}
}

//void NVIC_EnableIRQ(IRQn_Type IRQn)
void SetUSARTIRQ(TUART *UART, TBool Enable){
	if (Enable==true){
		switch(UART->Number){
			case 1:NVIC_EnableIRQ(USART1_IRQn); break;
			case 2:NVIC_EnableIRQ(USART2_IRQn); break;
			case 3:NVIC_EnableIRQ(USART3_IRQn); break;
		}
	}else{
		switch(UART->Number){
			case 1:NVIC_DisableIRQ(USART1_IRQn); break;
			case 2:NVIC_DisableIRQ(USART2_IRQn); break;
			case 3:NVIC_DisableIRQ(USART3_IRQn); break;
		}
	}
}


void SetDMAIRQ(TDMAChannel *DMA, TBool Enable){
	if (Enable==true){
		switch(DMA->Channel){
			case 1:NVIC_EnableIRQ(DMA1_Channel1_IRQn);break;
			case 2:NVIC_EnableIRQ(DMA1_Channel2_IRQn);break;
			case 3:NVIC_EnableIRQ(DMA1_Channel3_IRQn);break;
			case 4:NVIC_EnableIRQ(DMA1_Channel4_IRQn);break;
			case 5:NVIC_EnableIRQ(DMA1_Channel5_IRQn);break;
			case 6:NVIC_EnableIRQ(DMA1_Channel6_IRQn);break;
			case 7:NVIC_EnableIRQ(DMA1_Channel7_IRQn);break;
		}
	}else{
		switch(DMA->Channel){
			case 1:NVIC_DisableIRQ(DMA1_Channel1_IRQn);break;
			case 2:NVIC_DisableIRQ(DMA1_Channel2_IRQn);break;
			case 3:NVIC_DisableIRQ(DMA1_Channel3_IRQn);break;
			case 4:NVIC_DisableIRQ(DMA1_Channel4_IRQn);break;
			case 5:NVIC_DisableIRQ(DMA1_Channel5_IRQn);break;
			case 6:NVIC_DisableIRQ(DMA1_Channel6_IRQn);break;
			case 7:NVIC_DisableIRQ(DMA1_Channel7_IRQn);break;
		}
	}
}

void SetUARTMode(TUART *UART){
	uint32 CR1,CR3;
	EnableUSARTRCC(UART);
	USART_TypeDef *USART=GetUSART(UART);
	USART->CR1&=0x0000; //switch off
	USART->CR2&=0x0000;
	USART->CR3&=0x0000;
	USART->BRR&=0x0000;
	USART->BRR=ConvertBaud(UART->Baud);
	USART->CR1|=(UART->Parity<<9);
	USART->CR2|=(UART->StopBit<<12);
	if (UART->Parity) USART->CR1|=1<<12;  //M bit IF PARITY SET THEN M=1
	if (UART->ReceiverEnable) USART->CR1|=1<<2;
	if (UART->TransmitterEnable) USART->CR1|=1<<3;
	if (UART->DMAReceiverEnable) USART->CR3|=1<<6;
	if (UART->DMATransmitterEnable) USART->CR3|=1<<7;

	if (UART->Interrupt.ParityError) USART->CR1|=1<<8;
	if (UART->Interrupt.TransmissionComplete) USART->CR1|=1<<6;
	if (UART->Interrupt.ReceivingComplete) USART->CR1|=1<<5;
	if (UART->Interrupt.IdleDetected) USART->CR1|=1<<4;
	if (UART->Interrupt.CTS) USART->CR3|=1<<10;
	if (UART->Interrupt.DMAError) USART->CR3|=1;

	USART->CR3|=UART->Mode; //set hardware Mode
	SetPinForUSART(UART);

	CR1=USART->CR1;
	CR3=USART->CR3;
	CR1&=0x1F0;
	CR3&=0x501;
	if ((CR1>0)||(CR3>0)){
		SetUSARTIRQ(UART,true);
	}else{
		SetUSARTIRQ(UART,false);
	};
	if (UART->Enable==true) USART->CR1|=1<<13;
}

void SetDMAMode(TDMAChannel *DMA){

	uint32 *temp,CR;
	temp=(uint32 *)RCC_AHB_Base;
	*temp = 0x01;
	DMA_Channel_TypeDef *DMAx=GetDMAChannel(DMA->Channel);
	DMAx->CCR&=0x0000;
	DMAx->CMAR=DMA->MemoryAddress;
	DMAx->CPAR=DMA->PeripheralAddress;
	DMAx->CNDTR=DMA->Size;
	DMAx->CCR|=(DMA->Priority<<12);
	DMAx->CCR|=(DMA->MDataSize<<10);
	DMAx->CCR|=(DMA->PDataSize<<8);
	if (DMA->Mem2MemMode) DMAx->CCR|=1<<14;
	if (DMA->MemoryInc) DMAx->CCR|=1<<7;
	if (DMA->PeripheralInc) DMAx->CCR|=1<<6;
	if (DMA->CircularMode) DMAx->CCR|=1<<5;
	if (DMA->Direction==ToPeripheral) DMAx->CCR|=1<<4;
	if (DMA->Interrupt.TransmissionError) DMAx->CCR|=1<<3;
	if (DMA->Interrupt.TransmissionHalf) DMAx->CCR|=1<<2;
	if (DMA->Interrupt.TransmissionComplete) DMAx->CCR|=1<<1;
	if (DMA->Enable) DMAx->CCR|=1;

	CR=DMAx->CCR;
	if(CR&0x000E){
		SetDMAIRQ(DMA,true);
	}else{
		SetDMAIRQ(DMA,false);
	}
}

void SendByteUART(TUART *UART,uint8 buf){
	USART_TypeDef *USART;
	USART=GetUSART(UART);
	uint16_t SR=0;
/*	TTime time;
	time.Count=1;
	time.isTick=true;
	*/
	SR=USART->SR;
	SR&=1<<6;
	while(SR){
		//USART->SR&=0x320;
		USART->DR=buf;
		SR=USART->SR;
		SR&=1<<6;
	}
	//taskYIELD();
	vTaskDelay(1);


}

void SendStringUART(TUART *UART,uint8 *buf){
	int i=0;
	while(buf[i]!=0){
		SendByteUART(UART,buf[i]);
		i++;
	}
}

GPIO_TypeDef *GetGPIO(TPin *Pin){
	GPIO_TypeDef *GPIO=GPIOA;
	switch(Pin->Port){
	case 'A': GPIO=GPIOA;	break;
	case 'B': GPIO=GPIOB;	break;
	case 'C': GPIO=GPIOC;	break;
	case 'D': GPIO=GPIOD;	break;
	default: GPIO=GPIOA;
	}
	return GPIO;
};

GPIO_TypeDef *GetGPIO2(TPin *Pin){
	GPIO_TypeDef *GPIO=GPIOA;
	uint32 c='A'-(Pin->Port);
	if ((c<0) || (c>4)) return GPIO;
	uint32 dif=0x0800;
	dif=dif+0x0400*c;
	GPIO=((GPIO_TypeDef *) ((((uint32_t)0x40000000) + 0x10000) + dif));
	return GPIO;
};

void SetPinMode(TPin *Pin, TPinMode *PinMode){
	EnableRCC(Pin);
	Pin->GPIO=GetGPIO(Pin);
	uint32 mask=0x0000000F;
	uint32 cfg=0x00000000;
	cfg=(uint32)PinMode->CNF;
	cfg<<=2;
	cfg|=(uint32)PinMode->Mode;
	if ((Pin->Pin)<8) {
		mask<<=(Pin->Pin)*4;
		mask=~mask;
		Pin->GPIO->CRL &=mask; //erase configure and mode bits;
		mask=cfg<<(Pin->Pin)*4;
		Pin->GPIO->CRL |=mask; //set configure and mode bits
	}else {
		mask<<=((Pin->Pin)-8)*4;
		mask=~mask;
		Pin->GPIO->CRH &=mask; //erase configure and mode bits;
		mask=cfg<<((Pin->Pin)-8)*4;
		Pin->GPIO->CRH |=mask; //set configure and mode bits
	};
}

void SetBit(TPin *Pin){
	Pin->GPIO->BSRR |=1<<(Pin->Pin);
}

void ReSetBit(TPin *Pin){
	Pin->GPIO->BRR |=1<<((Pin->Pin));
}

int GetBit(TPin *Pin){
	uint32 mask=0x1<<(Pin->Pin);
	uint32 value=Pin->GPIO->IDR;
	if ((value&mask)>0) return 1;
	return 0;
}

void _Delay(TTime Time){
	int i=0;
	if (Time.isTick==true) {
		vTaskDelay(Time.Count);
	} else {
		i=Time.Count*configTICK_RATE_HZ/1000;
		if (i<1) {
			i=1;
		};
		vTaskDelay(i);
	};
}

int TouchPin(TPin *Pin){
	TPinMode PinMode;
	uint32 count=0;
	PinMode.CNF=GenOutPP;
	PinMode.Mode=OutMode10MHz;
	SetPinMode(Pin,&PinMode);
	ReSetBit(Pin);	//erase Pin cap
	vTaskDelay(3);	//Delay
	PinMode.CNF=InFloat;
	PinMode.Mode=InMode;
	SetPinMode(Pin,&PinMode);
	while((GetBit(Pin))!=1){
		count++;
		if (count>10024) return -1; //error
	}
	return count;
}

void PWMPin(TPin *Pin, uint32 Width, TTime Time){
	uint32 i;
	TTime t;
	t=Time;
	t.Count=1;
	if (Width==0) {
		ReSetBit(Pin);
		_Delay(Time);
		return;
	};
	if (Width>=15) {
		SetBit(Pin);
		_Delay(Time);
		return;
	};
	while(Time.Count>0){
		SetBit(Pin);
		for(i=1;i<16;i++){
			_Delay(t);
			if (Width==i){
				ReSetBit(Pin);
			}
		};
		Time.Count-=15; //time will be reduced by 15ms or ticks - minimum time of loop
	};
}

void StartButtonAnimation(TButton *Button){
	uint32 i;
	TTime time;
	time.Count=125;
	time.isTick=false;
	for(i=8;i<16;i++){
		PWMPin((TPin *)&(Button->LightPin),i,time);
	}
}

void EndButtonAnimation(TButton *Button){
	uint32 i;
	TTime time;
	time.Count=125;
	time.isTick=false;
	for(i=15;i>8;i--){
		PWMPin((TPin *)&(Button->LightPin),i,time);
	}
}

void PushButtonAnimation(TButton *Button){
	TTime time;
	time.Count=100;
	time.isTick=false;
	if (Button->State.isPush==true) {
		PWMPin((TPin *)&Button->LightPin,15,time);
	} else {
		PWMPin((TPin *)&Button->LightPin,0,time);
	}
}

void CalibrationAnimation(TButton *Button){
	TTime time;
	time.Count=300;
	time.isTick=false;
	SetBit(&(Button->LightPin));
	_Delay(time);
	ReSetBit(&(Button->LightPin));
	_Delay(time);
}

void AnimateButton(TButton *Button){
	if (Button->State.isCalibrating==true){
		CalibrationAnimation(Button);
	};
	if (Button->State.isPush==false){
		if (Button->State.isPrevSelected!=Button->State.isNowSelected){
		//	StartButtonAnimation(Button);
		} else {
			PushButtonAnimation(Button);
		}
	} else {
		if (Button->State.isPrevSelected!=Button->State.isNowSelected){
		//	EndButtonAnimation(Button);
		} else {
			PushButtonAnimation(Button);
		}
	}
}

void DetectButton(TButton *Button){
	int Touch=0;
	TTime time;
	time.Count=100;
	time.isTick=false;
	if (Button->SenseDelay==0){
		CalibrationButton(Button);
		return;
	};

	Button->State.isPush=GetGroupState(Button->GroupId);
	Touch=TouchPin((TPin *)&Button->SensePin);
	if (Touch==-1) {
		Button->State.isCalibrating=true;
		_Delay(time);
		return;
	}

	if (Touch>(Button->SenseDelay)){
		Button->State.isPrevSelected=Button->State.isNowSelected;
		Button->State.isNowSelected=true;
		if (Button->State.isPrevSelected!=Button->State.isNowSelected){
			Button->State.isPush=~Button->State.isPush;
			Button->State.isPush?SetGroupState(Button->GroupId):ReSetGroupState(Button->GroupId);
			taskENTER_CRITICAL();
			EraseObj(&TempMessage,sizeof(TMessage));
			TempMessage.StartByte=STARTByte;
			TempMessage.EndByte=ENDByte;
			Button->State.isPush?strcpy(TempMessage.Command,PWR_ON):strcpy(TempMessage.Command,PWR_OFF);
			TempMessage.Argument[0]=Button->GroupId;
			strcpy(TempMessage.From,FROM_ME);
			strcpy(TempMessage.To,TO_DEVICE_1);
			TempMessage.Number=CounterMessage;
			TempMessage.TTL=3;
			AddMessage(&TransmiteArray,&TempMessage);
			taskEXIT_CRITICAL();
		}
		_Delay(time);
	} else {
		Button->State.isPrevSelected=Button->State.isNowSelected;
		Button->State.isNowSelected=false;
		time.Count=100;
		CounterMessage++; //make motherfucker random))
		_Delay(time);
	}
}

void CalibrationButton(TButton *Button){
	Button->State.isCalibrating=true;
	int a[10];
	int i,k,n;
	TTime time;
	time.Count=100;
	time.isTick=true;
	for(i=0;i<9;i++){	//measure Sense delay of button
		a[i]=TouchPin(&(Button->SensePin));
		_Delay(time);
	};
	for(n=0;n<10;n++){
		for(i=0;i<9;i++){
			if (a[i]>a[i+1]){
				k=a[i];
				a[i]=a[i+1];
				a[i+1]=k;
			};
		};
	};
	k=0;
	for(i=2;i<8;i++){	//throw out the extreme values
		k+=a[i];
	};
	Button->SenseDelay=(k/6)+2;
	Button->State.isCalibrating=false;
}



TBool GetGroupState(uint32 GroupId){
	if ((GroupId<ButtonsCount)&&(GroupId>=0)){
		return GroupStateArray[GroupId];
	}
	else
		return false;
}

void SetGroupState(uint32 GroupId){
	if ((GroupId<ButtonsCount)&&(GroupId>=0))
		GroupStateArray[GroupId]=true;
}

void ReSetGroupState(uint32 GroupId){
	if ((GroupId<ButtonsCount)&&(GroupId>=0))
		GroupStateArray[GroupId]=false;
}

void InitGroupState(){
	int i;
	for(i=0;i<ButtonsCount;i++){
		GroupStateArray[i]=false;
	}
}

void EraseButton(TButton *Button){
	Button->GroupId=0;
	Button->MagicId=0;
	Button->SenseDelay=0;
	Button->State.isCalibrating=false;
	Button->State.isNowSelected=false;
	Button->State.isPrevSelected=false;
	Button->State.isPush=false;
}

void SetLedLine(uint8 Channel, TBool Light){
	//
}

